package com.cskaoyan.wordmemorize.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cskaoyan.wordmemorize.common.constant.CommonConstant;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.dao.entity.UserPrivilegeUseStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocAISituationDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundLogDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.UserPrivilegeHistoryMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocAISituationMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocBoundLogMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocBoundStatisticsMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.converter.UserPrivilegeConverter;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.admin.UserVocAISituationDTO;
import com.cskaoyan.wordmemorize.dto.app.*;
import com.cskaoyan.wordmemorize.request.AIReviewReadCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserFavoriteCommand;
import com.cskaoyan.wordmemorize.request.UserVocExampleSentenceCommand;
import com.cskaoyan.wordmemorize.service.UserPrivilegeService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserPrivilegeServiceImpl implements UserPrivilegeService {
    @Autowired
    UserMapper userMapper;

    @Autowired
    UserFavoriteMapper userFavoriteMapper;

    @Autowired
    UserPrivilegeConverter userPrivilegeConverter;

    @Autowired
    VocMapper vocMapper;

    @Autowired
    UserVocRevMapper userVocRevMapper;

    @Autowired
    VocMeaningMapper vocMeaningMapper;

    @Autowired
    UserNotRememberMapper userNotRememberMapper;

    @Autowired
    UserVocExampleSentenceMapper userVocExampleSentenceMapper;

    @Autowired
    VocChapBookMapper vocChapBookMapper;

    @Autowired
    VocBookMapper vocBookMapper;

    @Override
    public UserVocBookStatisticsDTO getSelectedBookStatistics(Long userId, Long bookId) {
        VocBookDO vocBookDO = vocBookMapper.selectById(bookId);
        Integer totalCount = vocBookDO.getVocCount();

        Integer notStartedWordsCount = userVocRevMapper.getNotStartedWordsCount(userId, bookId);
        Integer familiarWordsCount = userVocRevMapper.getFamiliarWordsCount(userId, bookId);
        Integer generalWordsCount = userVocRevMapper.getGeneralWordsCount(userId, bookId);
        Integer unFamiliarWordsCount = userVocRevMapper.getUnFamiliarWordsCount(userId, bookId);

        UserVocBookStatisticsDTO statisticsDTO = new UserVocBookStatisticsDTO();
        statisticsDTO.setTotal(totalCount);
        statisticsDTO.setNotStarted(notStartedWordsCount);
        statisticsDTO.setFamiliar(familiarWordsCount);
        statisticsDTO.setGeneral(generalWordsCount);
        statisticsDTO.setUnFamiliar(unFamiliarWordsCount);
        statisticsDTO.setUnSelected(totalCount - notStartedWordsCount - familiarWordsCount - generalWordsCount - unFamiliarWordsCount);
        return statisticsDTO;
    }

    @Override
    public void addFavoriteBulk(List<UserFavoriteCommand> userFavoriteCommand, Long userId) {
        // 请求体JSON为[{"vocId":"1851797124792655873"},{"vocId":"1851796506044735489"}]
        // 即在插入user_favorite表之前，需要先查voc表为其vocContent赋值，
        // 再查user_voc_rev，为selected赋值，如果在该复习表中，说明已被选中g'i
        List<UserFavoriteDO> userFavoriteDOS = userPrivilegeConverter.userFavoriteDOs2DTOs(userFavoriteCommand);

        userFavoriteDOS.forEach(userFavoriteDO -> {
            userFavoriteDO.setUserId(userId);
            Long vocId = userFavoriteDO.getVocId();
            VocDO vocDO = vocMapper.selectById(vocId);
            userFavoriteDO.setVocContent(vocDO.getContent());
            LambdaQueryWrapper<UserVocRevDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserVocRevDO::getVocId, vocId)
                    .eq(UserVocRevDO::getUserId, userId);
            List<UserVocRevDO> userVocRevDOS = userVocRevMapper.selectList(queryWrapper);
            if (CollectionUtils.isEmpty(userVocRevDOS)) {
                userFavoriteDO.setSelected(0);
            } else {
                userFavoriteDO.setSelected(1);
            }

            // 防止同一个用户重复收藏同一个单词
            LambdaQueryWrapper<UserFavoriteDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserFavoriteDO::getUserId, userId)
                    .eq(UserFavoriteDO::getVocId, userFavoriteDO.getVocId());
            UserFavoriteDO Do = userFavoriteMapper.selectOne(wrapper);
            if (Do == null) {
                userFavoriteMapper.insert(userFavoriteDO);
            } else {
                userFavoriteMapper.update(userFavoriteDO, wrapper);
            }
        });
    }

    @Override
    public void addFavorite(UserFavoriteCommand userFavoriteCommand, Long userId) {
        // {"vocId":"1851796192180772865","vocContent":"abstract","selected":1}，需要赋予userId
        UserFavoriteDO userFavoriteDO = userPrivilegeConverter.userFavoriteCommand2DO(userFavoriteCommand);
        userFavoriteDO.setUserId(userId);

        // 防止同一个用户重复收藏同一个单词
        LambdaQueryWrapper<UserFavoriteDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFavoriteDO::getUserId, userId)
                .eq(UserFavoriteDO::getVocId, userFavoriteDO.getVocId());
        UserFavoriteDO Do = userFavoriteMapper.selectOne(queryWrapper);
        if (Do == null) {
            userFavoriteMapper.insert(userFavoriteDO);
        } else {
            userFavoriteMapper.update(userFavoriteDO, queryWrapper);
        }
    }

    @Override
    public void cancelFavorite(List<Long> ids, Long userId) {
        LambdaQueryWrapper<UserFavoriteDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFavoriteDO::getUserId, userId)
                .in(UserFavoriteDO::getVocId, ids);
        userFavoriteMapper.delete(queryWrapper);
    }

    @Override
    public PageDTO<UserFavoriteDTO> getUserFavoriteList(PageRequest pageRequest, Long userId) {
        Integer pageNum = pageRequest.getPageNum();
        Integer count = pageRequest.getCount();
        String keyword = pageRequest.getKeyword();

        List<UserFavoriteDO> userFavoriteDOList;
        LambdaQueryWrapper<UserFavoriteDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFavoriteDO::getUserId, userId);
        if (pageNum == null) {
            if (keyword != null && !keyword.isEmpty()) {
                queryWrapper.like(UserFavoriteDO::getVocContent, keyword);
            }
            userFavoriteDOList = userFavoriteMapper.selectList(queryWrapper);
        } else {
            Page<UserFavoriteDO> page = new Page<>(pageNum, count);
            if (keyword != null && !keyword.isEmpty()) {
                queryWrapper.like(UserFavoriteDO::getVocContent, keyword);
            }
            Page<UserFavoriteDO> userFavoriteDOPage = userFavoriteMapper.selectPage(page, queryWrapper);
            userFavoriteDOList = userFavoriteDOPage.getRecords();
        }
        userFavoriteDOList.forEach(userFavoriteDO -> {
            Long vocId = userFavoriteDO.getVocId();
            LambdaQueryWrapper<VocMeaningDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(VocMeaningDO::getVocId, vocId);
            List<VocMeaningDO> vocMeaningDOS = vocMeaningMapper.selectList(wrapper);
            userFavoriteDO.setInterpretations(vocMeaningDOS);
        });
        PageDTO<UserFavoriteDTO> userFavoriteDTOPageDTO;
        if (pageNum == null) {
            userFavoriteDTOPageDTO = userPrivilegeConverter.userFavoriteDOPage2PageDTO(userFavoriteDOList, (long) userFavoriteDOList.size());
        } else {
            LambdaQueryWrapper<UserFavoriteDO> wrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserFavoriteDO::getUserId, userId);
            if (keyword != null && !keyword.isEmpty()) {
                queryWrapper.like(UserFavoriteDO::getVocContent, keyword);
            }
            List<UserFavoriteDO> totalList = userFavoriteMapper.selectList(queryWrapper);
            userFavoriteDTOPageDTO = userPrivilegeConverter.userFavoriteDOPage2PageDTO(userFavoriteDOList, (long) totalList.size());
        }
        return userFavoriteDTOPageDTO;
    }

    @Override
    public void addUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {
        UserVocExampleSentenceDO userVocExampleSentenceDO = userPrivilegeConverter.userVocExampleSentenceCommand2DO(command);
        userVocExampleSentenceDO.setUserId(userId);
        userVocExampleSentenceMapper.insert(userVocExampleSentenceDO);
    }

    @Override
    public PageDTO<DisplayUserVocSentenceDTO> getUserVocSentence(PageRequest pageRequest, Long userId) {

        // 1. 参数校验
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        // 2. 直接查询用户的自建例句
        LambdaQueryWrapper<UserVocExampleSentenceDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserVocExampleSentenceDO::getUserId, userId);

        if (pageRequest.getKeyword() != null && !pageRequest.getKeyword().isEmpty()) {
            wrapper.like(UserVocExampleSentenceDO::getSentence, pageRequest.getKeyword())
                    .or()
                    .like(UserVocExampleSentenceDO::getMeaning, pageRequest.getKeyword());
        }

        // 3. 先查询全部数据（不再使用分页查询）
        List<UserVocExampleSentenceDO> allRecords = userVocExampleSentenceMapper.selectList(wrapper);

        // 4. 按单词分组（使用完整数据集）
        Map<Long, List<UserVocExampleSentenceDO>> examplesByVocId = allRecords.stream()
                .collect(Collectors.groupingBy(UserVocExampleSentenceDO::getVocId));

        // 5. 手动分页逻辑
        int pageSize = pageRequest.getCount() != null ? pageRequest.getCount() : 10;
        int pageNum = pageRequest.getPageNum() != null ? pageRequest.getPageNum() : 1;
        int start = (pageNum - 1) * pageSize;

        List<DisplayUserVocSentenceDTO> resultList = examplesByVocId.entrySet().stream()
                .skip(start)
                .limit(pageSize)
                .map(entry -> {
                    Long vocId = entry.getKey();
                    VocDO voc = vocMapper.selectById(vocId);
                    if (voc == null) return null;

                    DisplayUserVocSentenceDTO dto = new DisplayUserVocSentenceDTO();
                    dto.setUserId(userId.toString());
                    dto.setVocId(vocId.toString());
                    dto.setVocContent(voc.getContent());
                    dto.setSentences(userPrivilegeConverter.userVocSentenceDOs2DTOs(entry.getValue()));
                    return dto;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 6. 返回分页结果（使用分组后的总数）
        return userPrivilegeConverter.displayUserVocSentenceDTOList2PageDTO(resultList, (long) examplesByVocId.size());

    }

    @Override
    public void updateUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {
        UserVocExampleSentenceDO updateDO = userPrivilegeConverter.userVocExampleSentenceCommand2DO(command);
        updateDO.setUserId(userId);
        LambdaUpdateWrapper<UserVocExampleSentenceDO> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(UserVocExampleSentenceDO::getId, updateDO.getId())
                .eq(UserVocExampleSentenceDO::getUserId, userId);
        userVocExampleSentenceMapper.update(updateDO, wrapper);
    }

    @Override
    public void deleteUserVocSentence(Long id) {

    }

    @Override
    public void notRemember(Long vocId, Long userId) {
        // 在user_voc_rev表中删除该用户该单词的信息，即不再复习
        LambdaQueryWrapper<UserVocRevDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserVocRevDO::getUserId, userId)
                .eq(UserVocRevDO::getVocId, vocId);
        userVocRevMapper.delete(queryWrapper);

        // 保证在user_not_remember表中同一用户的同一单词只有一个存在
        LambdaQueryWrapper<UserNotRememberDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserNotRememberDO::getUserId, userId)
                .eq(UserNotRememberDO::getVocId, vocId);
        UserNotRememberDO selectOne = userNotRememberMapper.selectOne(wrapper);
        UserNotRememberDO userNotRememberDO = new UserNotRememberDO();
        userNotRememberDO.setUserId(userId);
        userNotRememberDO.setVocId(vocId);
        if (selectOne == null) {
            userNotRememberMapper.insert(userNotRememberDO);
        }
    }

    @Override
    public void cancelNotRemember(Long vocId, Long userId) {
        LambdaQueryWrapper<UserNotRememberDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserNotRememberDO::getUserId, userId)
                .eq(UserNotRememberDO::getVocId, vocId);
        userNotRememberMapper.delete(queryWrapper);
    }

    @Override
    public List<UserReviewFillWordDTO> getUserReviewFillWordTopics(List<Long> vocIds) {
        return null;
    }

    @Override
    public List<UserReviewSingleChoiceDTO> getVocSingleChoiceTopic(List<Long> vocIds) {
        return null;
    }


    @Autowired
    UserVocAISituationMapper userVocAISituationMapper;
    @Autowired
    UserVocAISituationOptionMapper userVocAISituationOptionMapper;

    @Override
    public List<UserVocAISituationDTO> getAIReviewReadOptions() {
        // 全表查询
        List<UserVocAISituationDO> userVocAISituationDOS = userVocAISituationMapper.selectList(null);

        // 遍历userVocAISituationDOS,获取每个的id,获取每个的options
        for (UserVocAISituationDO userVocAISituationDO : userVocAISituationDOS) {
            // 根据userVocAISituationDOS的id进行去user_voc_ai_situation_option表里面查出对应的数据
            LambdaQueryWrapper<UserVocAISituationOptionDO> userVocAISituationOptionDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userVocAISituationOptionDOLambdaQueryWrapper.eq(UserVocAISituationOptionDO::getSituationId, userVocAISituationDO.getId());
            List<UserVocAISituationOptionDO> userVocAISituationOptionDOS = userVocAISituationOptionMapper.selectList(userVocAISituationOptionDOLambdaQueryWrapper);
            userVocAISituationDO.setOptions(userVocAISituationOptionDOS);
        }

        return userPrivilegeConverter.userVocAISituationDOs2DTOs(userVocAISituationDOS);

    }

    @Override
    public Integer getUserVocAIReadRemainFreeCount(Long userId) {
        LambdaQueryWrapper<UserPrivilegeUseStatisticsDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPrivilegeUseStatisticsDO::getUserId, userId);
        UserPrivilegeUseStatisticsDO userPrivilegeUseStatisticsDO = userPrivilegeHistoryMapper.selectOne(wrapper);
        LambdaQueryWrapper<UserDO> userDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userDOLambdaQueryWrapper.eq(UserDO::getId, userId);
        UserDO userDO = userMapper.selectOne(userDOLambdaQueryWrapper);
        if (userPrivilegeUseStatisticsDO == null) {
            userPrivilegeUseStatisticsDO = new UserPrivilegeUseStatisticsDO();
            userPrivilegeUseStatisticsDO.setUserId(userId);
            userPrivilegeUseStatisticsDO.setPrivilegeCode(CommonConstant.USER_PRIVILEGE_CODE_AI_READ);
            userPrivilegeUseStatisticsDO.setUseCount(0);
            userPrivilegeHistoryMapper.insert(userPrivilegeUseStatisticsDO);
            //还得查询用户等级，如果是12级，则返回10，否则返回0
            if (userDO.getLevelValue() == 12) {
                return 10;
            }
            return 0;
        }
        if (userDO.getLevelValue() == 12)
        {
            return 10 - userPrivilegeUseStatisticsDO.getUseCount() >= 0 ? 10 - userPrivilegeUseStatisticsDO.getUseCount() : 0;
        }
        return 0;
    }


    private final ChatClient chatClient;
    private final Resource systemResource;
    private final Resource userResource;

    // 通过构造函数注入 ChatClient 和资源
    public UserPrivilegeServiceImpl(
            ChatClient chatClient,
            @Value("classpath:/prompt/ai-read-system-message.st") Resource systemResource,
            @Value("classpath:/prompt/ai-read-user-message.st") Resource userResource
    ) {
        this.chatClient = chatClient;
        this.systemResource = systemResource;
        this.userResource = userResource;
    }

    @Autowired
    UserPrivilegeHistoryMapper userPrivilegeHistoryMapper;
    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;
    @Autowired
    UserVocBoundLogMapper userVocBoundLogMapper;

    @Override
    public List<AIReviewReadDTO> getAIReviewReadContent(AIReviewReadCommand command, Long userId) {
        // 根据userid去查看用户剩余的免费次数
        LambdaQueryWrapper<UserPrivilegeUseStatisticsDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPrivilegeUseStatisticsDO::getUserId, userId);
        UserPrivilegeUseStatisticsDO userPrivilegeUseStatisticsDO = userPrivilegeHistoryMapper.selectOne(wrapper);
        // 根据userid去查看用户剩余的可用单词上限
        LambdaQueryWrapper<UserVocBoundStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserVocBoundStatisticsDO::getUserId, userId);
        UserVocBoundStatisticsDO userVocBoundStatisticsDO = userVocBoundStatisticsMapper.selectOne(queryWrapper);

        // 构造用户提示词
        HashMap<String, Object> paramMap = new HashMap<>();
        // 设置场景
        paramMap.put("situation", command.getSituationName());
        // 设置场景中的选项
        paramMap.put("option", command.getOptionName());
        // 设置单词
        paramMap.put("words", command.getVocList().toString());
        // 设置模式
        if ("教育模式".equals(command.getSituationName())) {
            paramMap.put("type", "短文");
        } else if ("对话模式".equals(command.getSituationName())) {
            paramMap.put("type", "对话");
        } else {
            paramMap.put("type", "故事");
        }

        // 直接利用模版文件内容创建PromptTemplate对象
        SystemPromptTemplate systemPromptTemplate
                = new SystemPromptTemplate(systemResource);

        // 创建用户提示词信息
        Message systemMessage = systemPromptTemplate.createMessage();

        PromptTemplate userPrompt = new PromptTemplate(userResource, paramMap);
        // 构造用户提示词信息
        Message userMessage = userPrompt.createMessage();

        // 基于用户提示词信息和系统提示词信息，构造完整的提示词
        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        // 然后调用chatClient对象的方法发起请求即可
//         修改前
        List<AIReviewReadDTO> result = chatClient.prompt(prompt)
                .call()
                .entity(new ParameterizedTypeReference<List<AIReviewReadDTO>>() {
                });
//        // 修改后（适配单对象）
//        AIReviewReadDTO dto = chatClient.prompt(prompt)
//                .call()
//                .entity(AIReviewReadDTO.class); // 解析为单对象
//
//        List<AIReviewReadDTO> result = Collections.singletonList(dto); // 封装成列表
//调用上一个函数的返回值对免费使用次数检测，等于0次的时候
        if ( this.getUserVocAIReadRemainFreeCount(userId)==0) {
            if (userVocBoundStatisticsDO.getAvailable() <= 10) {
                throw new BusinessException(ResultCodeEnum.USER_VOC_BOUND_NOT_ENOUGH);
            } else {
                // 扣减用户的可用单词上限10，增加用户交易消耗的单词上限10
                userVocBoundStatisticsDO.setAvailable(userVocBoundStatisticsDO.getAvailable() - 10);
                userVocBoundStatisticsDO.setExchange(userVocBoundStatisticsDO.getExchange() + 10);
                userVocBoundStatisticsMapper.update(userVocBoundStatisticsDO, queryWrapper);
                // 增加一条单词上限变化记录(user_voc_bound_log)，
                // 变化类型为CommonConstant.USER_VOC_BOUND_CHANGE_TYPE_EXCHANGE，
                // 变化原因描述为CommonConstant.USER_VOC_BOUND_DESCRIPTION_AI_READ
                // 插入新日志记录（重要修改！）
                UserVocBoundLogDO log = new UserVocBoundLogDO();
                log.setUserId(userId);
                log.setType(CommonConstant.USER_VOC_BOUND_CHANGE_TYPE_EXCHANGE);
                log.setDescription(CommonConstant.USER_VOC_BOUND_DESCRIPTION_AI_READ);
                log.setCount(10);
                //创建时间
                log.setLogDate(LocalDate.now());
                userVocBoundLogMapper.insert(log); // 插入新记录
            }
        }else {
            // 增加用户对于AI阅读这个等级特权的使用次数
            userPrivilegeUseStatisticsDO.setUseCount(userPrivilegeUseStatisticsDO.getUseCount() + 1);
            userPrivilegeHistoryMapper.update(userPrivilegeUseStatisticsDO, wrapper);
        }
        return result;
    }
}
